from flask import Flask, jsonify, request  # 导入 Flask 核心模块
from flask_sqlalchemy import SQLAlchemy   # 导入 SQLAlchemy 用于数据库操作
from sqlalchemy import desc

app = Flask(__name__)  # 创建一个 Flask 应用实例

# 配置 MySQL 数据库连接信息
# 格式：mysql+pymysql://用户名:密码@主机地址/数据库名
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://:@localhost/finance'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False  # 禁用跟踪修改，提高性能

db = SQLAlchemy(app)  # 创建 SQLAlchemy 对象，用于与数据库交互

# 定义数据库表的模型类
class Transaction(db.Model):  # 继承自 SQLAlchemy 的 Model 类
    __tablename__ = 'transactions'  # 数据库表名，对应 MySQL 中的 `transactions`
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # 自增主键
    date = db.Column(db.Date, nullable=False)  # 记录的日期，不允许为空
    description = db.Column(db.String(255), nullable=False)  # 描述信息，不允许为空
    amount = db.Column(db.Numeric(10, 2), nullable=False)  # 金额，精确到小数点后两位
    type = db.Column(db.Enum('income', 'expense'), nullable=False)  # 类型（收入或支出），枚举类型

# 初始化数据库，确保表结构已经创建
with app.app_context():  # 确保操作发生在 Flask 应用上下文中
    db.create_all()  # 创建所有模型对应的表，如果表不存在

@app.route('/')
def home():
    return "你一定能成为百万富翁！"

# 接口：获取所有记录
@app.route('/transactions', methods=['GET'])
def get_transactions():
    """
    获取所有账本记录
    - 访问方式：GET /transactions
    - 返回值：JSON 格式的所有记录列表
    """
    transactions = Transaction.query.order_by(desc(Transaction.date)).all()
    result = [
        {
            'id': t.id,
            'date': t.date.strftime('%Y-%m-%d'),  # 格式化日期为字符串
            'description': t.description,
            'amount': float(t.amount),  # 将金额转为浮点数格式
            'type': t.type
        }
        for t in transactions
    ]
    return jsonify(result), 200  # 返回 JSON 格式的数据和状态码 200

# 接口：根据 ID 获取记录
@app.route('/transactions/<int:id>', methods=['GET'])
def get_transaction(id):
    """
    根据记录 ID 获取具体账本信息
    - 访问方式：GET /transactions/<id>
    - 返回值：JSON 格式的单条记录信息
    """
    transaction = Transaction.query.get(id)  # 根据主键 ID 查询记录
    if not transaction:  # 如果记录不存在
        return jsonify({'error': 'Transaction not found'}), 404  # 返回 404 错误
    result = {
        'id': transaction.id,
        'date': transaction.date.strftime('%Y-%m-%d'),
        'description': transaction.description,
        'amount': float(transaction.amount),
        'type': transaction.type
    }
    return jsonify(result), 200  # 返回记录信息和状态码 200

# 接口：添加新记录
@app.route('/transactions', methods=['POST'])
def add_transaction():
    """
    添加一条新的账本记录
    - 访问方式：POST /transactions
    - 请求数据：JSON 格式的记录信息
    """
    data = request.get_json()  # 获取请求中的 JSON 数据
    # 创建新的记录对象
    new_transaction = Transaction(
        date=data['date'],
        description=data['description'],
        amount=data['amount'],
        type=data['type']
    )
    db.session.add(new_transaction)  # 将新记录添加到数据库会话中
    db.session.commit()  # 提交会话，保存到数据库
    return jsonify({'message': 'Transaction added successfully!'}), 201  # 返回成功信息和状态码 201

# 接口：更新记录
@app.route('/transactions/<int:id>', methods=['PUT'])
def update_transaction(id):
    """
    更新指定 ID 的账本记录
    - 访问方式：PUT /transactions/<id>
    - 请求数据：JSON 格式的更新内容
    """
    data = request.get_json()  # 获取请求中的 JSON 数据
    transaction = Transaction.query.get(id)  # 根据主键 ID 查询记录
    if not transaction:  # 如果记录不存在
        return jsonify({'error': 'Transaction not found'}), 404  # 返回 404 错误
    # 更新记录字段，如果请求中未提供某字段则保留原值
    transaction.date = data.get('date', transaction.date)
    transaction.description = data.get('description', transaction.description)
    transaction.amount = data.get('amount', transaction.amount)
    transaction.type = data.get('type', transaction.type)
    db.session.commit()  # 提交会话，保存修改
    return jsonify({'message': 'Transaction updated successfully!'}), 200  # 返回成功信息和状态码 200

# 接口：删除记录
@app.route('/transactions/<int:id>', methods=['DELETE'])
def delete_transaction(id):
    """
    删除指定 ID 的账本记录
    - 访问方式：DELETE /transactions/<id>
    """
    transaction = Transaction.query.get(id)  # 根据主键 ID 查询记录
    if not transaction:  # 如果记录不存在
        return jsonify({'error': 'Transaction not found'}), 404  # 返回 404 错误
    db.session.delete(transaction)  # 从数据库会话中删除记录
    db.session.commit()  # 提交会话，删除记录
    return jsonify({'message': 'Transaction deleted successfully!'}), 200  # 返回成功信息和状态码 200

# 接口：计算结余
@app.route('/balance', methods=['GET'])
def calculate_balance():
    """
    计算账本的结余
    - 访问方式：GET /balance
    - 返回值：JSON 格式的结余信息
    """
    # 查询所有收入和支出
    total_income = db.session.query(db.func.sum(Transaction.amount)).filter(Transaction.type == 'income').scalar() or 0
    total_expense = db.session.query(db.func.sum(Transaction.amount)).filter(Transaction.type == 'expense').scalar() or 0
    
    # 计算结余
    balance = total_income - total_expense

    # 返回结余结果
    return jsonify({
        'total_income': float(total_income),
        'total_expense': float(total_expense),
        'balance': float(balance)
    }), 200

# 主程序入口
if __name__ == '__main__':
    """
    运行 Flask 应用
    - `debug=True`：开启调试模式，可以在开发过程中实时查看错误日志和代码修改效果
    """
    app.run(host='0.0.0.0', port=5000, debug=True)
